﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Rung.Net.Base;
using Rung.Net.Events;

namespace Rung.Net.Session
{
    public class SessionServer : Simple.SimpleServer, IDisposable
    {
        private System.Timers.Timer timer;
        private bool isCheckTimeout = false;

        /// <summary>
        /// 是否开启静默连接超时自动断开。
        /// </summary>
        public bool IsCheckTimeout
        {
            get { return isCheckTimeout; }
            set
            {
                this.isCheckTimeout = value;
                if (value)
                    timer.Start();
                else
                    timer.Stop();
            }
        }
        /// <summary>
        /// 连接在静默状态下保持的最长时间。
        /// </summary>
        public int TimeoutSecond
        { get; set; }
        /// <summary>
        /// 检测静默连接超时的频率（3秒遍历一次所有连接的空闲情况）。
        /// </summary>
        public const int CheckTimeoutInterval = 3 * 1000;

        /// <summary>
        /// 会话结束事件。
        /// </summary>
        public event SessionEndEventHandler OnSessionEnd;

        public SessionServer(int timeoutSecond)
            : base()
        {
            this.TimeoutSecond = timeoutSecond;
        }

        public SessionServer()
            : this(10 * 60)
        {
            this.timer = new System.Timers.Timer(1000);
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);

            this.IsCheckTimeout = true;

            base.OnReceived += new NetClientReceivedEventHandler<byte[]>(SessionServer_OnReceived);
        }

        protected override NetBaseStream<byte[]> CreateStream(NetworkStream ns, EndPoint ep)
        {
            return new SessionStream(ns, ep);
        }

        protected override void OnClientStopped(object sender, NetStreamStoppedEventArgs e)
        {
            if (OnSessionEnd != null)
            {
                SessionEndEventArgs args = new SessionEndEventArgs(e.Guid);
                OnSessionEnd(this, args);
            }

            base.Clients.Remove(e.Guid);
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (this.IsOnline && this.ClientCount > 0)
            {
                ClientItem<byte[]>[] cs = this.Clients.Values.ToArray();
                for (int i = 0; i < cs.Length; i++)
                {
                    if (cs[i].LastInteractionTime.AddSeconds(this.TimeoutSecond) <= DateTime.Now)
                    {
                        this.KillSession(cs[i].Id);
                    }
                }
            }
        }

        /// <summary>
        /// 终止会话。
        /// </summary>
        private void KillSession(Guid guid)
        {
            Session.SessionStream ss = base.Clients[guid].Stream as Session.SessionStream;
            if (ss == null)
                throw new Exception("服务端网络流为空或者类型错误。");
            else
                ss.KillSession();
        }

        void SessionServer_OnReceived(object sender, NetClientReceivedEventArgs<byte[]> e)
        {
            this.Clients[e.Guid].LastInteractionTime = DateTime.Now;
        }

        #region IDisposable 成员

        public void Dispose()
        {
            base.Dispose();
            this.timer.Dispose();
        }

        #endregion
    }
}
